# -*- coding: utf-8 -*-
__all__ = ['Root']
import turbogears as tg
from cherrypy import request
from cherrypy.lib.cptools import serve_file
from turbogears import controllers, expose, flash, redirect, paginate
from model import *
from datetime import datetime
from mimetypes import guess_type

class Root(controllers.RootController):
    """The root controller of the application."""

    DEFAULT_PAGE_ITEM_LIMIT = 10

    @expose(template="yale.templates.page")
    def default(self, url=None, **kw):
        if not url:
            raise redirect('index')
        else:
            page = Page.find(url)
            if page:
                return dict(page=page, bread=self.getBreadCrumb(page))
            else:
                raise redirect('index')

    @expose()
    def view(self, id=None, **kw):
        if not id:
            raise redirect('index')
        else:
            v = Viewable.get(int(id))
            if not v:
                raise redirect('index')
            else:
                t = type(v)
                if t is Page:
                    raise redirect('pages', pid = id)
                elif t is News:
                    raise redirect('news', nid = id)
                elif t is Event:
                    raise redirect('events', eid = id)
                elif t is Collection:
                    raise redirect('collections', cid = id)
                elif t is Gallery:
                    raise redirect('galleries', gid = id)
                elif t is Photo:
                    raise redirect('viewimage', pid = id)
                elif t is File:
                    raise redirect('download', id = id)
                else:
                    raise redirect('index')

    @expose(template="yale.templates.welcome")
    def index(self, **kw):
        news = News.query.filter(None).limit(5)
        events = Event.getEvents().limit(5)
        return dict(news=news, events=events, eventdates=[e.starttime.strftime('%Y%m%d') for e in events], bread=self.getBreadCrumb())

    @expose(template="yale.templates.admin")
    def admin(self, **kw):
        return dict(bread=self.getBreadCrumb('Admin Panel'))

    @expose(template="yale.templates.news")
    @paginate('allnews', limit=DEFAULT_PAGE_ITEM_LIMIT)
    def news(self, nid=None, **kw):
        allnews = News.query.filter(None)
        if nid:
            news = News.get(int(nid))
            return dict(allnews = allnews, news = news, bread=self.getBreadCrumb(news))
        else:
            return dict(allnews = allnews, news = None, bread=self.getBreadCrumb('News'))

    @expose(template="yale.templates.editnews")
    def editnews(self, nid=None, **kw):
        if not nid:
            return dict(news = None, bread=self.getBreadCrumb("New News"))
        else:
            news = News.get(int(nid))
            return dict(news = news, bread=self.getBreadCrumb(news))

    @expose()
    def addnews(self, title="", summary="", content="", nid=None, **kw):
        n = News.addOrEdit(title, summary, content, nid)
        flash("News has been modified." if nid else "News has been created.")
        raise redirect("news", nid=n.id)

    @expose()
    def delnews(self, nid=None, **kw):
        if nid:
            News.destroy(nid)
        raise redirect("news")

    @expose(template="yale.templates.events")
    @paginate('allevents', limit=DEFAULT_PAGE_ITEM_LIMIT)
    def events(self, eid=None, past=False, date=None, **kw):
        allevents = Event.getEvents(all=past, date=date)
        if eid:
            event = Event.get(int(eid))
            return dict(allevents = allevents, event = event, bread=self.getBreadCrumb(event))
        else:
            return dict(allevents = allevents, event = None, bread=self.getBreadCrumb("Events" if not past else "All Events"))

    @expose(template="yale.templates.editevent")
    def editevent(self, eid=None, **kw):
        if eid:
            event = Event.get(int(eid))
            return dict(event = event, bread=self.getBreadCrumb(event))
        else:
            return dict(event = None, bread=self.getBreadCrumb("New Event"))

    @expose()
    def addevent(self, title="", summary="", desc="", location="", starttime="", endtime="", eid=None, **kw):
        e = Event.addOrEdit(title, summary, desc, location, starttime, endtime, eid)
        flash("Event has been modified." if eid else "Event has been created.")
        raise redirect('events', eid=e.id)

    @expose()
    def delevent(self, eid=None, **kw):
        if eid:
            Event.destroy(eid)
        raise redirect("events")

    @expose(template="yale.templates.collections")
    @paginate('allcollections', limit=DEFAULT_PAGE_ITEM_LIMIT)
    def collections(self, cid=None, **kw):
        allcolls = Collection.query.filter(None)
        if cid:
            coll = Collection.get(int(cid))
            return dict(allcollections = allcolls, collection = coll, bread=self.getBreadCrumb(coll))
        else:
            return dict(allcollections = allcolls, collection = None, bread=self.getBreadCrumb("Collections"))

    @expose(template="yale.templates.editcollection")
    def editcollection(self, cid=None, **kw):
        if cid:
            coll = Collection.get(int(cid))
            return dict(collection = coll, bread=self.getBreadCrumb(coll))
        else:
            return dict(collection = None, bread=self.getBreadCrumb("New Collection"))

    @expose()
    def addcollection(self, title="", cid=None, **kw):
        c = Collection.addOrEdit(title, cid)
        flash("Collection has been renamed." if cid else "Collection has been created.")
        raise redirect('collections', cid=c.id)

    @expose(template="yale.templates.galleries")
    def galleries(self, gid=None, **kw):
        galleries = Gallery.query.filter(None)
        if gid:
            gallery = Gallery.get(int(gid))
            return dict(galleries=galleries, gallery=gallery, bread=self.getBreadCrumb(gallery))
        else:
            return dict(galleries=galleries, gallery=None, bread=self.getBreadCrumb("Galleries"))

    @expose(template="yale.templates.editgallery")
    def editgallery(self, gid=None, **kw):
        if gid:
            gallery = Gallery.get(int(gid))
            return dict(gallery=gallery, bread=self.getBreadCrumb(gallery))
        else:
            return dict(gallery=None, bread=self.getBreadCrumb("New Gallery"))

    @expose()
    def addgallery(self, title="", desc="", gid=None, **kw):
        g = Gallery.addOrEdit(title=title, desc=desc, id=gid)
        flash("Gallery has been modified." if gid else "Gallery has been created.")
        raise redirect('galleries', gid=g.id)

    @expose(template="yale.templates.pages")
    @paginate('pages', limit=DEFAULT_PAGE_ITEM_LIMIT)
    def pages(self, pid=None, cid=None, **kw):
        if pid:
            page = Page.get(int(pid))
            if page:
                return dict(collection = page.parent, page = page, pages = [], bread=self.getBreadCrumb(page))
            else:
                return dict(collection = None, pages = Page.query.filter(Page.parent==None), page=None, bread=self.getBreadCrumb("Pages"))
        elif cid:
            coll = Collection.get(int(cid))
            return dict(collection = coll, pages = coll.getPages(), page=None, bread=self.getBreadCrumb(coll))
        else:
            return dict(collection = None, pages = Page.query.filter(Page.parent==None), page=None, bread=self.getBreadCrumb("Pages"))

    @expose(template="yale.templates.editpage")
    def editpage(self, pid=None, cid=None, **kw):
        if cid:
            collection = Collection.get(int(cid))
        else:
            collection = None
        if pid:
            page = Page.get(int(pid))
            return dict(page = page, collection = collection, bread=self.getBreadCrumb(page))
        else:
            return dict(page = None, collection = collection, bread=self.getBreadCrumb('New Page'))

    @expose()
    def addpage(self, title="", url="", summary="", content="", pid=None, cid=None, **kw):
        p = Page.addOrEdit(title=title, url=url, summary=summary, content=content, cid=cid, id=pid)
        flash("Page has been modified." if pid else "Page has been created.")
        raise redirect("pages", pid=p.id)

    @expose(template="yale.templates.users")
    def users(self, uid=None, **kw):
        users = User.query.filter(None)
        if uid:
            user = User.get(int(uid))
            return dict(user=user, users=users, bread=self.getBreadCrumb(user))
        else:
            return dict(user=None, users=users, bread=self.getBreadCrumb("Users"))

    @expose(template="yale.templates.edituser")
    def edituser(self, uid=None, **kw):
        if uid:
            user = User.get(int(uid))
            return dict(user=user, bread=self.getBreadCrumb(user) + '&nbsp;&gt;&gt;&nbsp;<a href="edituser?uid=%d">Edit</a>'%user.id)
        else:
            return dict(user=None, bread=self.getBreadCrumb('<a href="users">Users</a>&nbsp;&gt;&gt;&nbsp;<a href="edituser">Add User</a>'))

    @expose()
    def adduser(self, name, email, phone="", dob="", desc="", website="", uid=None, **kw):
        u = User.addOrEdit(name=name, email=email, phone=phone, dob=dob, desc=desc, website=website, id=uid)
        flash("User info has been modified." if uid else "User has been added.")
        raise redirect('users', uid=u.id)

    @expose()
    def exportusers(self, **kw):
        f = User.exportUsers()
        raise redirect(f.url)

    @expose(template="yale.templates.images")
    def images(self, pid=None, **kw):
        if pid:
            parent = Viewable.get(int(pid))
            images = Photo.query.filter(Photo.parent == parent)
        else:
            images = Photo.query.filter(None)
        return dict(images=images)

    @expose(template="yale.templates.viewimage")
    def viewimage(self, pid=None, **kw):
        if pid:
            photo = Photo.get(int(pid))
            return dict(image=photo, bread=self.getBreadCrumb(photo))
        else:
            raise redirect('images')

    @expose(template="yale.templates.viewimages")
    @paginate('images', limit=1)
    def viewimages(self, pid=None, id=None, **kw):
        if pid:
            parent = Viewable.get(int(pid))
            images = Photo.query.filter(Photo.parent == parent)
        else:
            parent = None
            images = Photo.query.filter(None)
        if id:
            image = Photo.get(int(id))
            pageidx = images.all().index(image)
            print 'pageidx', pageidx
            raise redirect('viewimages', pid=pid, images_tgp_no=pageidx+1)
        else:
            return dict(images=images, parent=parent, bread=self.getBreadCrumb(parent))

    @expose()
    def getimage(self, id=None, **kw):
        if id:
            abspath = Photo.get(int(id)).abspath
            mimetype, enc = guess_type(abspath)
            return serve_file(abspath, contentType=mimetype)
        else:
            return ''

    @expose()
    def download(self, id=None, **kw):
        if id:
            f = File.get(int(id))
            return serve_file(f.abspath, "application/x-download", "attachment", f.filename)
        else:
            flash("File not found.")
            raise redirect('index')

    @expose()
    def upload(self, file, parentid=None, title="", desc="", **kw):
        if parentid:
            parent = Viewable.get(int(parentid))
        else:
            parent = None
        if parent:
            if parent.isA(Gallery):
                p = parent.uploadPhoto(file=file, title=title, desc=desc, cover=kw.get('cover', False))
                flash("Uploaded successfully.")
                raise redirect('galleries', gid=parent.id)
        if file.type[:5] == 'image':
            up = Photo.create(file=file, parent=parent, title=title, desc=desc)
        else:
            up = File.create(file=file, parent=parent, title=title, desc=desc)
        flash("Uploaded successfully. &nbsp; <a href='%s'>View</a>" % up.url)
        if parent:
            raise redirect(parent.url)
        else:
            raise redirect('uploadfile')

    @expose(template="yale.templates.uploadfile")
    def uploadfile(self, parentid=None, **kw):
        breadstr = '&nbsp;&gt;&gt;&nbsp;<a href="%s">Upload</a>' % request.browser_url
        if parentid:
            parent = Viewable.get(int(parentid))
            return dict(parent=parent, setcover=parent.isA(Gallery), bread=self.getBreadCrumb(parent)+breadstr)
        else:
            return dict(parent=None, setcover=False, bread=self.getBreadCrumb('Upload'))

    @expose(template="yale.templates.sitemap")
    def sitemap(self, **kw):
        return dict(sitemap=self.getSiteMap(), bread=self.getBreadCrumb('Site map'))

    @expose()
    def eventrss(self, **kw):
        return Event.rss()

    @expose()
    def newsrss(self, **kw):
        return News.rss()

    @expose()
    def rss(self, pid=None, **kw):
        if pid:
            parent = Viewable.get(int(pid))
            t = type(parent)
            if t is Collection or t is Gallery:
                return t.rss()
        raise redirect('index')

    @expose(format="json")
    def urlisunique(self, url="", **kw):
        if not url:
            return dict(unique = 0)
        else:
            if url in dir(Root) + Page.getURLs():
                return dict(unique = 0)
            else:
                return dict(unique = 1)

    def getBreadCrumb(self, obj=None):
        bread = ['<a href="/">Home</a>']
        t = type(obj)
        if isinstance(obj, Viewable):
            b = ['<a href="view?id=%d">%s</a>' % (obj.id, obj.title)]
            while obj.parent != None:
                obj = obj.parent
                b.append('<a href="view?id=%d">%s</a>' % (obj.id, obj.title))
            tt = type(obj)
            if tt is News:
                b.append('<a href="news">News</a>')
            elif tt is Event:
                b.append('<a href="events">Events</a>')
            elif tt is Collection:
                b.append('<a href="collections">Collections</a>')
            elif tt is Gallery:
                b.append('<a href="galleries">Galleries</a>')
            b.reverse()
            bread += b
        elif t is User:
            bread.append('<a href="users">Users</a>')
            bread.append('<a href="users?uid=%d">%s</a>'%(obj.id, obj.name))
        elif t is str:
            bread.append('<a href="%s">%s</a>' % (request.browser_url, obj))
        elif t is list:
            bread += obj
        return '&nbsp;&gt;&gt;&nbsp;'.join(bread)

    def getSiteMap(self, parent=None):
        v = Viewable.query.filter(Viewable.parent==parent)
        ret = dict()
        if parent is None:
            ret['title'] = 'Home'
            ret['link'] = '/'
            ret['children'] = map(self.getSiteMap, v)
        else:
            ret['title'] = parent.title
            ret['link'] = parent.url
            ret['children'] = map(self.getSiteMap, v)
        return ret
        

    
        
            

















        
